/******************************************************************************* * Copyright (c) 2000, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.search2.internal.ui; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Iterator; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableContext; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.IWorkbenchSiteProgressService; import org.eclipse.search.internal.ui.SearchPlugin; import org.eclipse.search.internal.ui.SearchPluginImages; import org.eclipse.search.internal.ui.SearchPreferencePage; import org.eclipse.search.ui.IQueryListener; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.ISearchResult; import org.eclipse.search.ui.ISearchResultViewPart; import org.eclipse.search2.internal.ui.text.PositionTracker; public class InternalSearchUI { //The shared instance. private static InternalSearchUI fgInstance; // contains all running jobs private HashMap<ISearchQuery, SearchJobRecord> fSearchJobs; private QueryManager fSearchResultsManager; private PositionTracker fPositionTracker; private SearchViewManager fSearchViewManager; public static final Object FAMILY_SEARCH = new Object(); private class SearchJobRecord { public ISearchQuery query; public Job job; public boolean isRunning; public SearchJobRecord(ISearchQuery job) { this.query= job; this.isRunning= false; this.job= null; } } private class InternalSearchJob extends Job { private SearchJobRecord fSearchJobRecord; public InternalSearchJob(SearchJobRecord sjr) { super(sjr.query.getLabel()); fSearchJobRecord= sjr; } @Override protected IStatus run(IProgressMonitor monitor) { fSearchJobRecord.job= this; searchJobStarted(fSearchJobRecord); IStatus status= null; int origPriority= Thread.currentThread().getPriority(); try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); } catch (SecurityException e) {} try{ status= fSearchJobRecord.query.run(monitor); } finally { try { Thread.currentThread().setPriority(origPriority); } catch (SecurityException e) {} searchJobFinished(fSearchJobRecord); } fSearchJobRecord.job= null; return status; } @Override public boolean belongsTo(Object family) { return family == InternalSearchUI.FAMILY_SEARCH; } } private void searchJobStarted(SearchJobRecord record) { record.isRunning= true; getSearchManager().queryStarting(record.query); } private void searchJobFinished(SearchJobRecord record) { record.isRunning= false; fSearchJobs.remove(record.query); getSearchManager().queryFinished(record.query); } /** * The constructor. */ public InternalSearchUI() { fgInstance= this; fSearchJobs= new HashMap<>(); fSearchResultsManager= new QueryManager(); fPositionTracker= new PositionTracker(); fSearchViewManager= new SearchViewManager(fSearchResultsManager); PlatformUI.getWorkbench().getProgressService().registerIconForFamily(SearchPluginImages.DESC_VIEW_SEARCHRES, FAMILY_SEARCH); } /** * @return returns the shared instance. */ public static InternalSearchUI getInstance() { if (fgInstance ==null) fgInstance= new InternalSearchUI(); return fgInstance; } public ISearchResultViewPart getSearchView() { return getSearchViewManager().getActiveSearchView(); } private IWorkbenchSiteProgressService getProgressService() { ISearchResultViewPart view= getSearchView(); if (view != null) { IWorkbenchPartSite site= view.getSite(); if (site != null) return view.getSite().getAdapter(IWorkbenchSiteProgressService.class); } return null; } public boolean runSearchInBackground(ISearchQuery query, ISearchResultViewPart view) { if (isQueryRunning(query)) return false; // prepare view if (view == null) { getSearchViewManager().activateSearchView(true); } else { getSearchViewManager().activateSearchView(view); } addQuery(query); SearchJobRecord sjr= new SearchJobRecord(query); fSearchJobs.put(query, sjr); Job job= new InternalSearchJob(sjr); job.setPriority(Job.BUILD); job.setUser(true); IWorkbenchSiteProgressService service= getProgressService(); if (service != null) { service.schedule(job, 0, true); } else { job.schedule(); } return true; } public boolean isQueryRunning(ISearchQuery query) { SearchJobRecord sjr= fSearchJobs.get(query); return sjr != null && sjr.isRunning; } public IStatus runSearchInForeground(IRunnableContext context, final ISearchQuery query, ISearchResultViewPart view) { if (isQueryRunning(query)) { return Status.CANCEL_STATUS; } // prepare view if (view == null) { getSearchViewManager().activateSearchView(true); } else { getSearchViewManager().activateSearchView(view); } addQuery(query); SearchJobRecord sjr= new SearchJobRecord(query); fSearchJobs.put(query, sjr); if (context == null) context= new ProgressMonitorDialog(null); return doRunSearchInForeground(sjr, context); } private IStatus doRunSearchInForeground(final SearchJobRecord rec, IRunnableContext context) { try { context.run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { searchJobStarted(rec); try { IStatus status= rec.query.run(monitor); if (status.matches(IStatus.CANCEL)) { throw new InterruptedException(); } if (!status.isOK()) { throw new InvocationTargetException(new CoreException(status)); } } catch (OperationCanceledException e) { throw new InterruptedException(); } finally { searchJobFinished(rec); } } }); } catch (InvocationTargetException e) { Throwable innerException= e.getTargetException(); if (innerException instanceof CoreException) { return ((CoreException) innerException).getStatus(); } return new Status(IStatus.ERROR, SearchPlugin.getID(), 0, SearchMessages.InternalSearchUI_error_unexpected, innerException); } catch (InterruptedException e) { return Status.CANCEL_STATUS; } return Status.OK_STATUS; } public static void shutdown() { InternalSearchUI instance= fgInstance; if (instance != null) instance.doShutdown(); } private void doShutdown() { Iterator<SearchJobRecord> jobRecs= fSearchJobs.values().iterator(); while (jobRecs.hasNext()) { SearchJobRecord element= jobRecs.next(); if (element.job != null) element.job.cancel(); } fPositionTracker.dispose(); fSearchViewManager.dispose(fSearchResultsManager); } public void cancelSearch(ISearchQuery job) { SearchJobRecord rec= fSearchJobs.get(job); if (rec != null && rec.job != null) rec.job.cancel(); } public QueryManager getSearchManager() { return fSearchResultsManager; } public SearchViewManager getSearchViewManager() { return fSearchViewManager; } public PositionTracker getPositionTracker() { return fPositionTracker; } public void addQueryListener(IQueryListener l) { getSearchManager().addQueryListener(l); } public ISearchQuery[] getQueries() { return getSearchManager().getQueries(); } public void removeQueryListener(IQueryListener l) { getSearchManager().removeQueryListener(l); } public void removeQuery(ISearchQuery query) { if (query == null) { throw new IllegalArgumentException(); } cancelSearch(query); getSearchManager().removeQuery(query); fSearchJobs.remove(query); } public void addQuery(ISearchQuery query) { if (query == null) { throw new IllegalArgumentException(); } establishHistoryLimit(); getSearchManager().addQuery(query); } private void establishHistoryLimit() { int historyLimit= SearchPreferencePage.getHistoryLimit(); QueryManager searchManager= getSearchManager(); if (historyLimit >= searchManager.getSize()) { return; } int numberQueriesNotShown= 0; SearchViewManager searchViewManager= getSearchViewManager(); ISearchQuery[] queries= searchManager.getQueries(); for (int i= 0; i < queries.length; i++) { ISearchQuery query= queries[i]; if (!searchViewManager.isShown(query)) { if (++numberQueriesNotShown >= historyLimit) { removeQuery(query); } } } } public void removeAllQueries() { for (Iterator<ISearchQuery> queries= fSearchJobs.keySet().iterator(); queries.hasNext();) { ISearchQuery query= queries.next(); cancelSearch(query); } fSearchJobs.clear(); getSearchManager().removeAll(); } public void showSearchResult(SearchView searchView, ISearchResult result, boolean openInNew) { if (openInNew) searchView= (SearchView)getSearchViewManager().activateSearchView(true, openInNew); showSearchResult(searchView, result); } private void showSearchResult(SearchView searchView, ISearchResult result) { getSearchManager().touch(result.getQuery()); searchView.showSearchResult(result); } }